# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt


import frappe
from frappe import _, get_all


def execute(filters=None):
	columns = [
		{
			"label": _("Payroll Number"),
			"fieldtype": "Link",
			"fieldname": "payroll_no",
			"options": "Payroll Entry",
			"width": 150,
		},
		{
			"label": _("Debit A/C Number"),
			"fieldtype": "Int",
			"fieldname": "debit_account",
			"hidden": 1,
			"width": 200,
		},
		{
			"label": _("Payment Date"),
			"fieldtype": "Data",
			"fieldname": "payment_date",
			"width": 100,
		},
		{
			"label": _("Employee Name"),
			"fieldtype": "Link",
			"fieldname": "employee_name",
			"options": "Employee",
			"width": 200,
		},
		{"label": _("Bank Name"), "fieldtype": "Data", "fieldname": "bank_name", "width": 50},
		{
			"label": _("Employee A/C Number"),
			"fieldtype": "Int",
			"fieldname": "employee_account_no",
			"width": 50,
		},
	]

	if frappe.db.has_column("Employee", "ifsc_code"):
		columns.append({"label": _("IFSC Code"), "fieldtype": "Data", "fieldname": "bank_code", "width": 100})

	columns += [
		{"label": _("Currency"), "fieldtype": "Data", "fieldname": "currency", "width": 50},
		{
			"label": _("Net Salary Amount"),
			"fieldtype": "Currency",
			"options": "currency",
			"fieldname": "amount",
			"width": 100,
		},
	]

	data = []

	accounts = get_bank_accounts()
	payroll_entries = get_payroll_entries(accounts, filters)
	salary_slips = get_salary_slips(payroll_entries)

	if frappe.db.has_column("Employee", "ifsc_code"):
		get_emp_bank_ifsc_code(salary_slips)

	for salary in salary_slips:
		if (
			salary.bank_name
			and salary.bank_account_no
			and salary.debit_acc_no
			and salary.status in ["Submitted", "Paid"]
		):
			row = {
				"payroll_no": salary.payroll_entry,
				"debit_account": salary.debit_acc_no,
				"payment_date": frappe.utils.formatdate(salary.modified.strftime("%Y-%m-%d")),
				"bank_name": salary.bank_name,
				"employee_account_no": salary.bank_account_no,
				"bank_code": salary.ifsc_code,
				"employee_name": salary.employee + ": " + salary.employee_name,
				"currency": frappe.get_cached_value("Company", filters.company, "default_currency"),
				"amount": salary.net_pay,
			}
			data.append(row)

	return columns, data


def get_bank_accounts():
	accounts = [d.name for d in get_all("Account", filters={"account_type": "Bank"})]
	return accounts


def get_payroll_entries(accounts, filters):
	payroll_filter = [
		("payment_account", "IN", accounts),
		("number_of_employees", ">", 0),
		("Company", "=", filters.company),
	]
	if filters.to_date:
		payroll_filter.append(("posting_date", "<", filters.to_date))

	if filters.from_date:
		payroll_filter.append(("posting_date", ">", filters.from_date))

	entries = get_all("Payroll Entry", payroll_filter, ["name", "payment_account"])

	payment_accounts = [d.payment_account for d in entries]
	entries = set_company_account(payment_accounts, entries)
	return entries


def get_salary_slips(payroll_entries):
	payroll = [d.name for d in payroll_entries]
	salary_slips = get_all(
		"Salary Slip",
		filters=[("payroll_entry", "IN", payroll)],
		fields=[
			"modified",
			"net_pay",
			"bank_name",
			"bank_account_no",
			"payroll_entry",
			"employee",
			"employee_name",
			"status",
		],
	)

	payroll_entry_map = {}
	for entry in payroll_entries:
		payroll_entry_map[entry.name] = entry

	# appending company debit accounts
	for slip in salary_slips:
		if slip.payroll_entry:
			slip["debit_acc_no"] = payroll_entry_map[slip.payroll_entry]["company_account"]
		else:
			slip["debit_acc_no"] = None

	return salary_slips


def get_emp_bank_ifsc_code(salary_slips):
	emp_names = [d.employee for d in salary_slips]
	ifsc_codes = get_all("Employee", [("name", "IN", emp_names)], ["ifsc_code", "name"])

	ifsc_codes_map = {code.name: code.ifsc_code for code in ifsc_codes}

	for slip in salary_slips:
		slip["ifsc_code"] = ifsc_codes_map[slip.employee]

	return salary_slips


def set_company_account(payment_accounts, payroll_entries):
	company_accounts = get_all(
		"Bank Account", [("account", "in", payment_accounts)], ["account", "bank_account_no"]
	)
	company_accounts_map = {}
	for acc in company_accounts:
		company_accounts_map[acc.account] = acc

	for entry in payroll_entries:
		company_account = ""
		if entry.payment_account in company_accounts_map:
			company_account = company_accounts_map[entry.payment_account]["bank_account_no"]
		entry["company_account"] = company_account

	return payroll_entries
